/*
 *  Copyright 2012 Dirk Vranckaert
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package eu.vranckaert.vvl.activities;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import eu.vranckaert.vvl.model.TrafficInfoAlarm;
import eu.vranckaert.vvl.utils.context.Constants;
import eu.vranckaert.vvl.utils.context.Logger;
import eu.vranckaert.vvl.utils.context.Preference;

import java.util.*;

/**
 * User: DIRK VRANCKAERT
 * Date: 29/02/12
 * Time: 10:39
 */
public class AlarmReceiver extends BroadcastReceiver {
    private static final String LOG_TAG = AlarmReceiver.class.getSimpleName();

    public void onReceive(Context context, Intent intent) {
        List<TrafficInfoAlarm> alarms = Preference.getAlarms(context);

        if (Logger.isLogEnabled()) {
            if (alarms.size() == 0)
                Log.d(LOG_TAG, "No alarms have to be scheduled");
            else
                Log.d(LOG_TAG, alarms.size() + " alarms have to be scheduled");
        }

        for (TrafficInfoAlarm alarm : alarms) {
            launchAlarm(context, alarm);
        }
    }
    
    private void launchAlarm(Context ctx, TrafficInfoAlarm alarm) {
        List<Integer> alarmRequestCodes = alarm.getAlarmIds();
        AlarmManager am = (AlarmManager)ctx.getSystemService(ctx.ALARM_SERVICE);

        if (!alarm.isRepeatingAlarm()) {
            if (Logger.isLogEnabled())
                Log.d(LOG_TAG, "Setting up a single-shot alarm (" + alarm.toString() + ")");

            int alarmRequestCode = alarmRequestCodes.get(0);
            am.set(AlarmManager.RTC_WAKEUP, alarm.getAlarmTime().getTimeInMillis(), alarm.getPendingIntent(ctx, alarmRequestCode));

            if (Logger.isLogEnabled())
                Log.d(LOG_TAG, "Single-shot alarm scheduled for " + alarm.getAlarmTime().getTime());
        } else {
            if (alarm.getAlarmTime().before(Calendar.getInstance())) {
                alarm.getAlarmTime().add(Calendar.DAY_OF_MONTH, 1);
            }
            
            if (Logger.isLogEnabled())
                Log.d(LOG_TAG, "Setting up a repeating alarm (" + alarm.toString() + ")");

            Map<Constants.WeekDays, Integer> mappingNextSevenDays = getNextSevenDaysMapping(alarm);
            long weekInterval = 7 * AlarmManager.INTERVAL_DAY;

            for (Constants.WeekDays weekDay : alarm.getRepeatingDays()) {
                Integer daysUntilDay = mappingNextSevenDays.get(weekDay);
                Calendar alarmTimeForDay = Calendar.getInstance();
                alarmTimeForDay.setTimeInMillis(alarm.getAlarmTime().getTimeInMillis());
                alarmTimeForDay.add(Calendar.DAY_OF_WEEK, daysUntilDay);

                int alarmRequestCode = alarmRequestCodes.get(alarm.getRepeatingDays().indexOf(weekDay));
                am.setRepeating(AlarmManager.RTC_WAKEUP, alarmTimeForDay.getTimeInMillis(), weekInterval, alarm.getPendingIntent(ctx, alarmRequestCode));
                if (Logger.isLogEnabled())
                    Log.d(LOG_TAG, "Repeating alarm scheduled for " + alarmTimeForDay.getTime() + " to be repeated every 7 days");
            }
        }
    }

    private Map<Constants.WeekDays, Integer> getNextSevenDaysMapping(TrafficInfoAlarm alarm) {
        List<Constants.WeekDays> weekDays = Arrays.asList(Constants.WeekDays.values());
        Integer[] weekDaysFromNow = new Integer[weekDays.size()];
        int currentDayOfWeek = alarm.getAlarmTime().get(Calendar.DAY_OF_WEEK);

        for (Constants.WeekDays weekDay : weekDays) {
            if (currentDayOfWeek == weekDay.getWeekDay()) {
                int dayDiff = 0;
                int index = weekDays.indexOf(weekDay);
                weekDaysFromNow[index] = dayDiff;
                for (int i=(index+1); i<weekDays.size(); i++) {
                    weekDaysFromNow[i] = ++dayDiff;
                }
                for (int i=0; i<index; i++) {
                    weekDaysFromNow[i] = ++dayDiff;
                }
                break;
            }
        }

        Map<Constants.WeekDays, Integer> weekdaysFromNowMapping = new HashMap<Constants.WeekDays, Integer>();
        for (Constants.WeekDays weekDay : weekDays) {
            weekdaysFromNowMapping.put(weekDay, weekDaysFromNow[weekDays.indexOf(weekDay)]);
        }

        return weekdaysFromNowMapping;
    }
}
